.. code:: ipython3 import os from seeq import spy import pandas as pd import numpy as np # Set the compatibility option so that you maximize the chance that SPy will remain compatible with your notebook/script spy.options.compatibility = 192 .. code:: ipython3 # Log into Seeq Server if you're not using Seeq Data Lab: spy.login(url='http://localhost:34216', credentials_file='../credentials.key', force=False) Asset Trees 4: Creating Accelerator Templates ============================================= The Seeq platform provides the basis for doing all sorts of analytics – leveraging Seeq Workbench, Seeq Organizer, Seeq Data Lab – with Seeq Cortex providing data connection and calculation capabilities. It can be useful for the Seeq community of partners and users to create *accelerators* that deploy proven, standardized analytic approaches in rapid fashion using SPy’s asset/workbook/topic templating capabilities in ``spy.assets``. For example, an expert in monitoring and optimizing large-scale HVAC installations might develop an *Accelerator Template* to deploy a set of useful calculations, visualizations and reports or dashboards that can handle variations in manufacturer, configuration etc and provide immediate value that can be expanded and built upon over time. This notebook illustrates how to use ``spy.assets`` infrastructure to create Accelerator Templates. If you haven’t used it before, it is recommended that you first explore the following: - :doc:`Asset Trees 2 - Templates ` to learn about the ``spy.assets`` infrastructure to create asset trees with calculations - :doc:`Asset Trees 3 - Report and Dashboard Templates ` to learn how to create workbooks and topics (reports/dashboards) This notebook will use the HVAC example data that is installed by default with the Seeq system. “Requirements” -------------- The most important concept with Accelerator Templates is **Requirements**. A Requirement specifies an “input” to the template – something that must be provided in order for the template to function. For example, if the template needs an ambient temperature signal in order to calculate an operational efficiency metric, that temperature signal is a Requirement. Furthermore, the operating limits may need to be provided, or perhaps the manufacturer/model of the equipment. These Requirements are the things that vary from installation to installation. The template can be written to adjust to these variations as long as it has the inputs it needs. Requirements are specified in a class like so: .. code:: ipython3 from seeq.spy.assets import Asset class HVAC_Monitoring_Requirements(Asset): @Asset.Requirement() def Compressor_Power(self, metadata): """ Compressor Power as measured at the power supply of the equipment itself. """ return { 'Type': 'Signal', 'Unit Of Measure Family': 'kW' } @Asset.Requirement() def Temperature(self, metadata): """ The ambient *external* temperature as measured in a neutral location away from HVAC inlet/outlet sites. > Note that this value may be derived from equipment sensors with a > suitable coefficient to account for location bias. """ return { 'Type': 'Signal', 'Unit Of Measure Family': 'F', 'Optional': True } Similar to ``@Asset.Attribute``, Requirements are specified as functions within a Python class, decorated with ``@Asset.Requirement``. The documentation for the function is useful to describe the expectations for the Requirement. For example, the ``Temperature`` signal that is supplied to meet one of the Requirements above must be an external temperature that is not affected by the operation of the HVAC unit. The return value is a Python dictionary that further constrains the input. In this case, ``Temperature`` must be a Signal whose unit of measure is compatible with ``F`` (so, either Fahrenheit, Celsius or Kelvin). ``Temperature`` is also marked with ``'Optional'`` equal to ``True``. This means that the template can handle the case where an adequate temperature signal cannot be supplied. The template may not be able to provide as many calculations, or perhaps those calculations will be less accurate. Analytics! ---------- Now let’s create a simple class that makes use of these two requirements. In this example, an ``Inefficient Operation`` condition is calculated by comparing ``Compressor Power`` and ``Temperature`` against hard-coded limits. (Such limits should likely be determined by manufacturer specifications or process control limits, but for now we’ll keep it simple.) Note how this new ``HVAC_Monitoring`` class is derived from the ``HVAC_Monitoring_Requirements``. This allows the ``Inefficient Operation`` calculation to refer to the members of the requirements class. .. code:: ipython3 class HVAC_Monitoring(HVAC_Monitoring_Requirements): @Asset.Attribute() def Inefficient_Operation(self, metadata): """ A condition that is present whenever the HVAC is running in ostensibly unnecessary environmental situations, resulting in inefficient use of power. Examples: * Ambient temperature is within control bounds and does not warrant cooling * Environmental conditions are such that HVAC system is operating outside of its range of capabilities """ if not self.Temperature(): return None return { 'Type': 'Condition', 'Formula Parameters': { '$power': self.Compressor_Power(), '$temp': self.Temperature() }, 'Formula': '$power > 20 kW and $temp < 60 F' } Input Tree ---------- The template is applied to an existing *input tree*. This tree must already be constructed, in whatever way makes sense for a particular use case. It may be different in each application of the template – different hierarchy, different organization. The template will be applied to the tree as it is constructed, and any roll-ups will correspond to the particular hierarchy present in the input tree. In this example, we will use the **Example** asset tree that comes with Seeq. So we assemble a *metadata DataFrame* by doing ``spy.search(recursive=True)``. .. code:: ipython3 # Grab the whole tree as the basis of the metadata DataFrame metadata_df = spy.search({ 'Path': 'Example' }, recursive=True) # Reduce the number of columns (just for readability) metadata_df = metadata_df[['ID', 'Path', 'Asset', 'Name', 'Type']] # This call prepares the metadata DataFrame by adding 'Build Path' and # 'Build Asset' columns. You can also specify a new root_asset_name, which # is often desired so that you can differentiate the output tree from the # input tree. spy.assets.prepare(metadata_df, root_asset_name='HVAC Monitoring') # Specify the Build Template. We want to target all leaf "Area" assets (for now) metadata_df.at[metadata_df['Build Asset'].str.startswith('Area '), 'Build Template'] = 'HVAC_Monitoring' metadata_df.head() Build and Push -------------- As with other uses of ``spy.assets``, we must now build and then push the results. .. code:: ipython3 build_df = spy.assets.build(HVAC_Monitoring, metadata_df) .. code:: ipython3 push_results_df = spy.push(metadata=build_df) If you click on the workbook link, you should see a new ``HVAC Monitoring`` tree in the **Data** tab with the expected hierarchy and an ``Inefficient Operation`` condition under each Area. Brochures --------- Once you have an accelerator created, you can generate a *brochure* that advertises the cool analytics that the accelerator provides. Execute the ``spy.assets.brochure()`` function like so: .. code:: ipython3 html = spy.assets.brochure(HVAC_Monitoring, output='html') # Write it to a file so we can view it in the browser os.makedirs('Output', exist_ok=True) with open('Output/hvac_monitoring_brochure.html', 'w') as f: f.write(html) API Reference Links ------------------- - :py:mod:`seeq.spy.assets`